// 
// Copyright (C) 2000-2003
// magustek co.
//

#ifndef MAGUS_RECURSIVE_MUTEX_HPP
#define MAGUS_RECURSIVE_MUTEX_HPP

#include <magus/config.hpp>
#include <magus/utility.hpp>
#include <magus/thread/detail/lock.hpp>
#include <magus/thread/detail/config.hpp>

#if defined(MAGUS_HAS_WINTHREADS)
#   include <stddef.h>
#elif defined(MAGUS_HAS_PTHREADS)
#   include <pthread.h>
#endif

namespace magus {

struct xtime;

class MAGUS_THREAD_DECL recursive_mutex : private noncopyable
{
public:
    friend class detail::thread::lock_ops<recursive_mutex>;

    typedef detail::thread::scoped_lock<recursive_mutex> scoped_lock;

    recursive_mutex();
    ~recursive_mutex();

private:
#if defined(MAGUS_HAS_WINTHREADS)
    typedef size_t cv_state;
#elif defined(MAGUS_HAS_PTHREADS)
    struct cv_state
    {
        long count;
        pthread_mutex_t* pmutex;
    };
#endif
    void do_lock();
    void do_unlock();
    void do_lock(cv_state& state);
    void do_unlock(cv_state& state);

#if defined(MAGUS_HAS_WINTHREADS)
    void* m_mutex;
    unsigned long m_count;
#elif defined(MAGUS_HAS_PTHREADS)
    pthread_mutex_t m_mutex;
    unsigned m_count;
#   if !defined(MAGUS_HAS_PTHREAD_MUTEXATTR_SETTYPE)
    pthread_cond_t m_unlocked;
    pthread_t m_thread_id;
    bool m_valid_id;
#   endif
#endif
};

class MAGUS_THREAD_DECL recursive_try_mutex : private noncopyable
{
public:
    friend class detail::thread::lock_ops<recursive_try_mutex>;

    typedef detail::thread::scoped_lock<recursive_try_mutex> scoped_lock;
    typedef detail::thread::scoped_try_lock<
        recursive_try_mutex> scoped_try_lock;

    recursive_try_mutex();
    ~recursive_try_mutex();

private:
#if defined(MAGUS_HAS_WINTHREADS)
    typedef size_t cv_state;
#elif defined(MAGUS_HAS_PTHREADS)
    struct cv_state
    {
        long count;
        pthread_mutex_t* pmutex;
    };
#endif
    void do_lock();
    bool do_trylock();
    void do_unlock();
    void do_lock(cv_state& state);
    void do_unlock(cv_state& state);

#if defined(MAGUS_HAS_WINTHREADS)
    void* m_mutex;
    unsigned long m_count;
#elif defined(MAGUS_HAS_PTHREADS)
    pthread_mutex_t m_mutex;
    unsigned m_count;
#   if !defined(MAGUS_HAS_PTHREAD_MUTEXATTR_SETTYPE)
    pthread_cond_t m_unlocked;
    pthread_t m_thread_id;
    bool m_valid_id;
#   endif
#endif
};

class MAGUS_THREAD_DECL recursive_timed_mutex : private noncopyable
{
public:
    friend class detail::thread::lock_ops<recursive_timed_mutex>;

    typedef detail::thread::scoped_lock<recursive_timed_mutex> scoped_lock;
    typedef detail::thread::scoped_try_lock<
        recursive_timed_mutex> scoped_try_lock;
    typedef detail::thread::scoped_timed_lock<
        recursive_timed_mutex> scoped_timed_lock;

    recursive_timed_mutex();
    ~recursive_timed_mutex();

private:
#if defined(MAGUS_HAS_WINTHREADS)
    typedef size_t cv_state;
#elif defined(MAGUS_HAS_PTHREADS)
    struct cv_state
    {
        long count;
        pthread_mutex_t* pmutex;
    };
#endif
    void do_lock();
    bool do_trylock();
    bool do_timedlock(const xtime& xt);
    void do_unlock();
    void do_lock(cv_state& state);
    void do_unlock(cv_state& state);

#if defined(MAGUS_HAS_WINTHREADS)
    void* m_mutex;
    unsigned long m_count;
#elif defined(MAGUS_HAS_PTHREADS)
    pthread_mutex_t m_mutex;
    pthread_cond_t m_unlocked;
    pthread_t m_thread_id;
    bool m_valid_id;
    unsigned m_count;
#endif
};

} // namespace magus

#include <magus/thread/detail/recursive_mutex_impl.hpp>

// Change Log:
//    16 JUN 03  Initial version.

#endif // MAGUS_RECURSIVE_MUTEX_HPP
